using PhraseCorrector.Common;
using PhraseCorrector.SimplePinyin;
using PhraseCorrector.SpellCorrect;
using PhraseCorrector.SpellLook;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;

namespace PhraseCorrector.DirectTanslate
{

    /**
     * 中文转英文类
     * 该C#类 ChineseToEnglish 实现了从英文到中文的翻译功能，主要分为以下几个部分：   
     *       词库初始化： 加载英文到中文的词库（CElibrary），如果本地文件存在则从文件加载，否则尝试其他方式加载。
     *       词库管理：提供方法向词库添加新词条及其对应的英文解释，并支持更新已有词条的解释。
     *       文本匹配：提供 FindAll 方法搜索给定内容在词库中的匹配项，通过分词和递归查找所有可能的术语组合，并根据匹配度排序返回结果。
     *       枚举器实现：实现 IEnumerable<string> 接口，允许遍历词库中的所有英文词条。
     */
    public class ChineseTraslator {

        #region 英译中词树变量

        // ///////////////////////////////////////////////////////////////////////////////
        /// <summary>
        /// 英文多单词树
        /// </summary>
        public static Dictionary<string, string> CElibrary = new Dictionary<string, string>();

        // ///////////////////////////////////////////////////////////////////////////////
        /// <summary>
        /// 最大容错单词个数
        /// </summary>
        private static int MaxLength { set; get; } = 0;

        // ///////////////////////////////////////////////////////////////////////////////
        /// <summary>
        /// 纠错词库对象（初始化时使用）
        /// </summary>
        private readonly English_Chinese_Dictionary ECDics = null;

        // ///////////////////////////////////////////////////////////////////////////
        /// <summary>
        /// 匹配结果
        /// </summary>
        private List<PhraseResult> Result { set; get; } = new List<PhraseResult>();

        // ///////////////////////////////////////////////////////////////////////////////
        /// <summary>
        /// 建议关键词数组
        /// </summary>
        private string[] SuggestArray { get; set; } = new string[0];

        // ///////////////////////////////////////////////////////////////////////////////
        /// <summary>
        /// 属性：保存最后一个单词。用于在单词操作中提供临时存储或上下文信息。
        /// </summary>
        private string LastWord { get; set; } = "";

        #endregion

        #region 中文词库的创建与更新
        // ///////////////////////////////////////////////////////////////////////////
        /// <summary>
        /// 初始化ChinesePhraselibrary类的实例。
        /// </summary>
        public ChineseTraslator() {
            if (CElibrary.Count == 0)
                throw new Exception("请先载入中文词库！");
        }

        // ///////////////////////////////////////////////////////////////////////////
        /// <summary>
        /// 装载词库
        /// </summary>
        /// <param name="english_Chinese_Dictionary"> 鞥含词典实例</param>
        public ChineseTraslator(English_Chinese_Dictionary english_Chinese_Dictionary) {
            ECDics = english_Chinese_Dictionary;
            // 装载英汉词库
            ChineseLoading();
            // 默认最大容错单词个数是短语最大长度的70%（当最大产犊为10个汉字时，则为7）
            MaxLength = (int)(ChineseSpell.SpellHandle.MaxLength * 1);
        }

        // ///////////////////////////////////////////////////////////////////////////
        /// <summary>
        /// 特定文件是否存在
        /// </summary>
        /// <returns>如果文件存在，则返回true；否则返回false</returns>
        private bool SpecializedIsExis {
            get {
                // 创建FileInfo对象，用于检查特定文件是否存在
                FileInfo fileInfo = new FileInfo(BasePath.SpecializedDictionaryPath);
                // 返回文件是否存在
                return fileInfo.Exists;
            }
        }

        // ///////////////////////////////////////////////////////////////////////////
        /// <summary>
        /// 载入常用词库
        /// </summary>
        public void ChineseLoading() {
            TryLoadSpecialedlibrary();
            if (BasePath.DicsModel == LibraryType.All || BasePath.DicsModel == LibraryType.Phrase) TryLoadlibrary();
            new ChineseSpell();
        }

        // ///////////////////////////////////////////////////////////////////////////
        /// <summary>
        /// 尝试加载专业字典。
        /// </summary>
        /// <remarks>
        /// 如果库文件存在，则从文件中加载。
        /// </remarks>
        public void TryLoadSpecialedlibrary() {
            if (SpecializedIsExis) LoadFromFile(BasePath.SpecializedDictionaryPath);
        }

        // ///////////////////////////////////////////////////////////////////////////
        /// <summary>
        /// 尝试加载基础字典。
        /// </summary>
        public void TryLoadBaselibrary() {
            if (BasePath.DicsModel == LibraryType.All || BasePath.DicsModel == LibraryType.Phrase)
                TryLoadlibrary();
        }

        // ///////////////////////////////////////////////////////////////////////////
        /// <summary>
        /// 尝试加载图书馆的双语词典数据
        /// </summary>
        public void TryLoadlibrary() {
            // 遍历英汉词典中的每一行
            foreach (var line in ECDics.English_Chinese_library)
                // 如果词典模型不是短语库模型，或者英文单词由多个单词组成（即包含空格），则添加到词典中
                if (BasePath.DicsModel != LibraryType.Phrase || line.Key.Split(' ').Length > 1)
                    Add(line.Value, line.Key);
        }

        // ///////////////////////////////////////////////////////////////////////////
        /// <summary>
        /// 逐行加载文件内容，并处理每一行。
        /// </summary>
        /// <param name="fInfo">要加载的文件信息。</param>
        private void LoadFromFile(string fInfo) {
            // 使用StreamReader读取文件内容
            using StreamReader sr1 = new StreamReader(fInfo);
            // 循环读取文件的每一行，直到文件结束
            while (sr1.Peek() != -1)
                ReadAndInsert(sr1.ReadLine());
        }

        // ///////////////////////////////////////////////////////////////////////////
        /// <summary>
        /// 读取一行文件内容，并尝试插入到术语字典中。
        /// </summary>
        /// <param name="line">一行文件内容。</param>
        private void ReadAndInsert(string line) {
            if (!string.IsNullOrEmpty(line))
                TryAdd(DicsUtilities.FormatECDicsLine(line.Split(' ')));
        }

        // ///////////////////////////////////////////////////////////////////////////
        /// <summary>
        /// 尝试将解析后的键值对添加到术语字典中。
        /// </summary>
        /// <param name="keyValue">解析后的键值对数组。</param>
        private void TryAdd(string[] keyValue) {
            // 如果解析出了键和值，则尝试添加到术语字典中
            if (keyValue.Length == 2 && Utilities.IsLetterBegin(keyValue[0]) && Utilities.IsChineseBegin(keyValue[1]))
                Add(keyValue[1], keyValue[0]);
        }

        #endregion

        #region 生成词树

        // ///////////////////////////////////////////////////////////////////////////////
        /// <summary>
        /// 添加术语到词树
        /// </summary>
        /// <param name="sentance">术语句子</param>
        /// <param name="chinese">对应的中文解释</param>
        public static void Add(string sentance, string english) {
            // 如果片段不存在于词树中，则将其添加，初始解释为空
            foreach (var item in sentance.Split('|'))
                AddNew(item, english);
        }

        // /////////////////////////////////////////////////////////////////////////////////
        /// <summary>
        /// 向词库中添加新的条目及其英文解释。
        /// 如果条目已存在，则更新其英文解释；如果条目不存在，则添加新的条目及其英文解释。
        /// </summary>
        /// <param name="item">要添加或更新的条目。</param>
        /// <param name="english">条目的英文解释。</param>
        public static void AddNew(string item, string english) {
            // 如果片段不存在于词树中，则将其添加，初始解释为空
            if (!CElibrary.TryGetValue(item, out string value))
                CElibrary[item] = english;
            else
                AppenfValue(value, item, english);
        }

        // /////////////////////////////////////////////////////////////////////////////////
        /// <summary>
        /// 添加值到字典中的方法
        /// </summary>
        /// <param name="value">当前值</param>
        /// <param name="item">字典中的条目</param>
        /// <param name="english">英文对照值</param>
        public static void AppenfValue(string value, string item, string english) {
            // 当当前值与英文对照值不相同时，将英文值添加到字典对应条目中
            if (value != english)
                CElibrary[item] += "|" + english;
        }

        #endregion

        #region 短语字典速查

        // ///////////////////////////////////////////////////////////////////////////////
        /// <summary>
        /// 获取查找结果(不分词)
        /// </summary>
        /// <param name="content">要查找的piny</param>
        /// <returns>返回查找结果</returns>
        public static PhraseResult Get(string content) {
            // 使用拼音字典和自定义正则表达式数组，转换查找内容
            return new PhraseResult() {
                Chinese = content,
                Words = new FastTree(CElibrary).TransformCustomizedWords(content.Split(' '))
            };
        }


        #endregion

        #region 纠错翻译器

        // //////////////////////////////////////////////////////////////////////////
        /// <summary>
        /// 拼写纠正方法，用于修正输入的术语。
        /// </summary>
        /// <param name="Phrase">需要进行拼写纠正的术语。</param>
        /// <returns>返回纠正后的术语结果。</returns>
        public static PhraseResult SpellPhraseCorrect(string Phrase) {

            // 计算术语的拼写纠正建议
            var suggestions = SpellPhraseCorrectCal(Phrase);

            // 如果有建议，则处理第一个建议，否则返回原始术语及默认值
            return (suggestions.Count() > 0)
                ? SpellPhraseCorrectResult(suggestions.First())
                : SpellPhraseCorrectEmptyResult(Phrase);
        }

        // //////////////////////////////////////////////////////////////////////////
        /// <summary>
        /// 计算术语的拼写纠正建议的辅助方法。
        /// 最多允许三个连续的删除错误。
        /// </summary>
        /// <param name="Phrase">需要计算的术语。</param>
        /// <returns>返回按相关性排序的建议列表。</returns>
        private static IOrderedEnumerable<SuggestItem> SpellPhraseCorrectCal(string Phrase) {
            // 返回按核心值降序排序的建议列表
            return ChineseSpell.SpellHandle.Lookup(Phrase, Verbosity.Closest, MaxLength).OrderByDescending(x => x.score);
        }

        // //////////////////////////////////////////////////////////////////////////
        /// <summary>
        /// 根据建议项生成拼写纠正结果。
        /// </summary>
        /// <param name="input">包含纠正建议的建议项。</param>
        /// <returns>返回包含纠正结果的 ECResult 对象。</returns>
        private static PhraseResult SpellPhraseCorrectResult(SuggestItem input) {
            var english = Get(input.term.Replace("_", " "));
            // 使用建议项中的数据生成纠正结果
            return new PhraseResult() {
                Chinese = input.term,
                Words = english.Words + "|" + Pinyin.GetPinyin(input.term),
                Distance = input.distance,
                Score = input.score,
            };
        }

        // //////////////////////////////////////////////////////////////////////////
        /// <summary>
        /// 生成拼写纠正空结果。
        /// </summary>
        /// <param name="input">输入的文本，当没有纠正建议时返回。</param>
        /// <returns>返回包含原始文本和默认值的 ECResult 对象。</returns>
        public static PhraseResult SpellPhraseCorrectEmptyResult(string input) {
            // 生成并返回没有纠正建议时的结果
            return new PhraseResult() {
                Chinese = input,
                Distance = 0,
                Score = 0,
            };
        }
        #endregion
    }
}
